#include "oper.h"
#include "systick.h"
#include "reader.h"
#include "pos_param.h"
#include <string.h>
#include "display.h"
#include "pos_timer.h"
#include "pos.h"
#include "RTClock.h"
#include "beep.h"
#include "rfid_rc522.h"
#include "TM1638.h"
#include "gd32e230c_bsp.h"
#include "oper.h"

extern volatile uint8_t DefendUID;

#define CARD_01_VER  0x01
#define CARD_02_VER  0x02
#define CARD_03_VER  0x03
#define CARD_5D_VER  0x5D
#define CARD_D6_VER  0xD6
#define CARD_F2_VER  0xF2
#define CARD_F9_VER  0xF9

uint8_t setDefaultKey[6];


//??????
static uint8_t JudgeAuthCode(void)
{
    if ((PosParam.AuthCode != Reader.Purse.AuthCode)) { // ??????
#ifdef SEGLCD 
        disp.Symbols(Error);
        disp.Symbols(Exclama);
    #endif
        disp.AuthCode ( Reader.Purse.AuthCode );
        Beep.BeepGap(3);

        CheckCardOn();
        return 1;
    }
    return 0;
}
//  功能卡CC
static void DoSet_CC_Card(void)
{
    PosParam.BackLight = 1;//液晶屏背光源开启
    PosParam.FreeUseMode= 0; //
    PosParam.DayLimitFlag = 0; //????
    PosParam.EnableUserCard = 0; //M1卡和CPU卡的标志位
    PosParam.SpecDeduInCrad = 0; //24??????????
    PosParam.SpecDeduMode = 0; //??????????
    PosParam.ChargeDelay = 0;      //?????????
    PosParam.RetenMoneyFlag = 0;   //????
	PosParam.RationMode = 0;       //??????
    //PosParam.SaveWorkParam();
    PosParam.LiterDisplay = 0;

    PosParam.SaveParam();
   // PosParam.SaveWorkParam();
    Beep.BeepGap(2);
    delay_ms(100);
    Beep.BeepTime(800);
}
//时钟卡
static void CardSetClock()
{
	GetClock();
    c.Year  = GNumBlock[7];
    c.Month = GNumBlock[8];
    c.Day   = GNumBlock[9];

    c.Hour   = GNumBlock[11];
    c.Minute = GNumBlock[12];
    c.Second = 0;

    SetClock (&c);
    Beep.BeepOnce();
}
//单路脉冲加减卡 90；91；
static void ConsumePlusMinus(uint8_t aPlus)
{
    static uint32_t  Pulse;
    static uint32_t Time_count;
#ifdef SEGLCD   
    if ( (PosParam.MeasureMode == 0x20) || (PosParam.MeasureMode == 0x60))//????
        disp.LcdData(12,0x01);      //????
    else
        disp.LcdData(11,0x01);   // ?????? ??
#endif
    Pulse = PosParam.OutPulse;
    if(aPlus == 1){   
        Pulse ++; 
        if(Pulse > 0xff){
            Pulse = 0;
        }  
    }else{   
        if(Pulse == 0){
            Pulse = 0xff;
        }else {
            Pulse --;
        }      
    }

    disp.OneNum(2, 0, Pulse / 100 % 10);
    disp.OneNum(3, 0, Pulse / 10 % 10);
    disp.OneNum(4, 0, Pulse % 10);
#ifdef DIGLED
    disp.OneNum(1, 0, '-');
    disp.OneNum(5, 0, '-');
#endif
    Beep.BeepTwinkle();

    SetTime13_Counter (on);
    while (CheckM1Card() == nil) {
        if (Time13_Count >= 2400) { // ????3????????????1
            if ((Time13_Count - 2450) >= 150 && Time13_Count != Time_count) {        // Time_Num-3000) >= 200  ??3??
                Time_count = Time13_Count;
                if(aPlus == 1) {  
                    Pulse ++;
                    if (Pulse > 0xff) {
                        Pulse = 0;
                    }
                } else {     
                    if(Pulse == 0) {
                        Pulse = 0xff;
                    } else {
                        Pulse --;  
                    }
                }       
                
                BEEP_ON;
                delay_ms(20);
                BEEP_OFF;

                disp.OneNum(2, 0, Pulse / 100 % 10);
                disp.OneNum(3, 0, Pulse / 10 % 10);
                disp.OneNum(4, 0, Pulse % 10);

                Time13_Count = 2450;
            } 
        }
    }
    if(Pulse == 0){
        disp.ErrorCode(601);  //????????
        Pulse = 1;
    }

    SetTime13_Counter(off);
    PosParam.OutPulse = Pulse;
    PosParam.SaveParam();
#ifdef SEGLCD 
    disp.Symbols(okLine);
#endif
    delay_ms(500);
}
//??????
static void PosIP_PlusMinus(uint8_t aPlus)
{
    uint16_t  POSIP_Temp;
    uint32_t Time_count;

    POSIP_Temp = PosParam.PosIP[1] + (uint16_t)(PosParam.PosIP[0] << 8);

    if (aPlus) {
        POSIP_Temp++;
        if (POSIP_Temp > 0xFFFF) {
            POSIP_Temp = 0;
        }
    } else {
        if ( POSIP_Temp == 0 ){
            POSIP_Temp = 0xFFFF;
        }else{
            POSIP_Temp--;
        }
            
    }

    disp.sIP(POSIP_Temp);
    Beep.BeepTwinkle();

    SetTime13_Counter(on);
    while (CheckM1Card() == nil) {
        if (Time13_Count / 1000 >= 3) {     // ????3????????????1
            if ((Time13_Count - 3000) >= 200 && Time13_Count != Time_count) {    // Time_Num-3000) >= 200  ??3??
                Time_count = Time13_Count;
                if (aPlus) {
                    POSIP_Temp++;
                    if (POSIP_Temp > 0xFFFF) {   
                        POSIP_Temp = 0;
                    }
                } else {
                    if (POSIP_Temp == 0) {
                        POSIP_Temp = 0xFFFF;
                    } else{
                        POSIP_Temp--;
                    }   
                }
                BEEP_ON;
                delay_ms(10);
                BEEP_OFF;

                disp.sIP(POSIP_Temp);
                Time13_Count = 3000;
            }
        }
    }
    SetTime13_Counter (off);
    PosParam.PosIP[0] = (unsigned char)(POSIP_Temp >> 8);
    PosParam.PosIP[1] = (unsigned char)(POSIP_Temp & 0x00FF);

    PosParam.SaveParam();
#ifdef SEGLCD
    disp.Symbols(okLine);
#endif
    delay_ms(500);
}

//功能卡 22 
static void OperCard_22(void)
{
    PosParam.DayLimit = ((uint16_t)GNumBlock[7] << 8) + (uint16_t)GNumBlock[8];
    if(( GNumBlock[7] == 0x00) && (GNumBlock[8] == 0x00)){
        PosParam.DayLimitFlag = 0;
    } else{    
        PosParam.DayLimitFlag = 1;
    }

    PosParam.OutPulse = GNumBlock[9];
    PosParam.OutFee = GNumBlock[11];
    if(PosParam.OutPulse == 0){
        disp.ErrorCode(601);
        PosParam.OutPulse = 1;
    }

    PosParam.SaveParam(); 
    Beep.BeepOnce();

    disp.OneNum(1, 0, GNumBlock[9] / 16);
    disp.OneNum(2, 0, GNumBlock[9] % 16);
    disp.segDash(3);    // ?? -
    disp.OneNum(4, 0, GNumBlock[11] / 16);
    disp.OneNum(5, 0, GNumBlock[11] % 16);
}
//功能卡 24
static void OperCard_24(void)
{
    if(GNumBlock[7] == 0x5A){
        PosParam.SpecDeduPulse = GNumBlock[8];
        PosParam.SpecDeduFee = GNumBlock[9];
        PosParam.SpecDeduMode = 1;

        if((GNumBlock[11] == 0x5A)){   
            PosParam.SpecDeduInCrad = 0; 
        } else{   
            PosParam.SpecDeduInCrad = 1; 
        }

        disp.OneNum(1, 0, PosParam.SpecDeduPulse / 16);
        disp.OneNum(2, 0, PosParam.SpecDeduPulse % 16);
        disp.segDash(3);    // ?? -
        disp.OneNum(4, 0, PosParam.SpecDeduFee / 16);
        disp.OneNum(5, 0, PosParam.SpecDeduFee % 16);
    }else{   
        PosParam.SpecDeduMode = 0; 
    }

    PosParam.SaveParam();
	Beep.BeepOnce();
}
//功能卡 25
static void OperCard_25(void)
{
    if(GNumBlock[7] == 0x5A){
        PosParam.RetenMoney     = ((uint16_t)GNumBlock[8] << 8) + (uint16_t)GNumBlock[9]; // ????BUF????
        PosParam.RetenMoneyFlag = 0x01;

        disp.WriteMulDig(1, 5, PosParam.RetenMoney);
    #ifdef SEGLCD
        disp.Symbols(Yuan);
        disp.Symbols(Limit);
        disp.Symbols(okLine);
    #endif
    }else{   
        PosParam.RetenMoneyFlag = 0x00; 
    }

    PosParam.SaveParam();
    Beep.BeepOnce();
}

static void OperCard_81(void)
{
    if(GNumBlock[9] == 0x5A){    
        PosParam.LiterDisplay = 1;
        PosParam.PulsesPerLiter = ((uint16_t)GNumBlock[7] << 8) + (uint16_t)GNumBlock[8];
        disp.OneNum(1,0,GNumBlock[7]/16);
        disp.OneNum(2,0,GNumBlock[7]/16);
        disp.segDash(3);
        disp.OneNum(4,0,GNumBlock[8]/16);
        disp.OneNum(5,0,GNumBlock[8]/16);
    }else{    
        PosParam.LiterDisplay = 0;
    }
    
    PosParam.SaveParam();
    Beep.BeepOnce();
}
//9A??????? QueryParame
static void OperCard_9A(void)
{
    static uint8_t status;
    static uint8_t atqa[2];
    static uint8_t Check_Step;

    Check_Step = 0;
    SetTime14_Counter(on);
    while (Check_Step != 9 && Time14_Count < 6) {
        PcdAntReset();
        status = PcdRequest(PICC_REQALL,atqa);
        if(status == MI_OK){
            Check_Step ++;
            disp.Clear();
            switch(Check_Step){
            case 1:
                disp.TotalConsum (PosParam.Amtall);
                break;
            case 2:
                disp.Balance (PosParam.DayLimit);
            #ifdef SEGLCD
                disp.Symbols(Limit);
            #elif defined DIGLED
                disp.OneNum(1,0,'L');
            #endif
                break;
            case 3:
            #ifdef DIGLED
                disp.OneNum(1, 0, '-');
            #endif
                disp.PlusFee(PosParam.OutPulse,PosParam.OutFee);
            #ifdef DUAL_MODE
                if(PosParam.DualMode == 0x5A)
                    disp.PlusFee(PosParam.Out1Pulse,PosParam.Out1Fee);
            #endif
                break;
            case 4:
            #ifdef DIGLED
                disp.OneNum(1, 0, '_');
            #endif
                disp.segDash(2); disp.segDash(3); disp.segDash(4); disp.segDash(5);
            #ifdef DUAL_MODE
                if(PosParam.DualMode == 0x5A){
                    disp.PlusFee(PosParam.Out2Pulse,PosParam.Out2Fee); 
                }
            #endif
                break;
            case 5:
                disp.AuthCode(PosParam.AuthCode);
                break;
            case 6:
                disp.segDash(2);
                disp.OneNum(3, 0, PosParam.MeasureMode / 16);    // ????????
                disp.OneNum(4, 0, PosParam.MeasureMode % 16);
                disp.segDash(5);
            #ifdef SEGLCD
                if ((PosParam.MeasureMode == 0x20)||(PosParam.MeasureMode == 0x60)||(PosParam.MeasureMode == 0x00)){    
                   disp.Symbols(ModePulse);         //????
                } else {   
                    disp.Symbols(ModeTime);         //??;}
                }  
            #endif
                break;
            case 7:
                disp.sIP(PosParam.PosIP[1] + (uint16_t)( PosParam.PosIP[0] << 8));
            #ifdef SEGLCD
                disp.OneNum(6 ,0 , 1);
                disp.LcdData ( 16, 0x07);   	
                disp.LcdData ( 15, 0X03);
                disp.LcdData ( 17, 0X04);
            #endif
                break;
            case 8:
                disp.WriteMulDig(1, 5, PosParam.StopSec);
            #ifdef SEGLCD
                disp.LcdData ( 17, 0X02);
            #elif defined DIGLED
                disp.OneNum(7,0,'T');
                disp.OneNum(8,1,'J');
            #endif
                break;
            default:
                Check_Step = 9;
                SetTime14_Counter(off);
                return ;
            }
            
            PcdAntReset();
            while (PcdRequest(PICC_REQALL,atqa) == MI_OK){
                PcdAntReset();
                Time14_Count = 0;
            }
            delay_ms(500);
        }
        status = MI_ERR;
    }

    SetTime14_Counter(off);
    Check_Step = 0;
}

static void OperCard_D5(void)
{
    memmove((void *)&PosParam.AuthCode, (void *)&GNumBlock[2], 2);
    PosParam.AuthCode = ((PosParam.AuthCode & 0x00FF) << 8) | ((PosParam.AuthCode & 0xFF00) >> 8); // 20220120
    memmove((void *)PosParam.PosIP, (void *)&GNumBlock[7], 2);

    PosParam.SaveParam();
    disp.AuthCode(Reader.Purse.AuthCode);
    Beep.BeepOnce();
}
 //功能卡D6;
static void OperCard_D6(void)
{
    if (GNumBlock[7] == 0x5A) 
    {     // ??????1
        PosParam.M1Purse.DataType = 1;
    } 
    else 
    {   
        PosParam.M1Purse.DataType = 0; 
    }

    if (GNumBlock[8] == 0x5A) 
    {      // ???? UID
        PosParam.Prev_UID = 1; 
    }else {   
        PosParam.Prev_UID = 0; 
    }

    if(GNumBlock[9] == 0x5A)
    {    
        PosParam.EnableUserCard = 0x01;         //仅读取CPU卡用户卡
    }else if(GNumBlock[9] == 0x6A) 
    {    
        PosParam.EnableUserCard = 0x02;         //仅读取M1卡用户卡
    }else {    
        PosParam.EnableUserCard = 0x00;         //CPU,M1 都读取
    }      

    if(GNumBlock[11] == 0x5A){
        PosParam.MaxBalance_Flag = 1;
        PosParam.MaxBalance      = ((uint16_t)GNumBlock[12] << 8) + (uint16_t)GNumBlock[13];
    }else {
        PosParam.MaxBalance_Flag = 0;
    }

    PosParam.SaveParam();
    //PosParam.SaveWorkParam();
    Beep.BeepOnce();
}



//????F1
static void OperCard_F1(void)
{
    if (GNumBlock[1] == CARD_02_VER) {
        if(GNumBlock[7] != 0x10 && GNumBlock[7] != 0x20 && GNumBlock[7] != 0x30 && GNumBlock[7] != 0x60){
            disp.ErrorCode(805);        // ??????
            CheckCardOn();
            return;
        }
        PosParam.MeasureMode = GNumBlock[7];
    #ifdef DUAL_MODE
        if(PosParam.DualControlMode == 0x01 || PosParam.DualControlMode == 0x6A) {   
            PosParam.DualControlMode_1 = GNumBlock[7];
            PosParam.DualControlMode_2 = GNumBlock[7];
        } else{
            PosParam.DualControlMode_1 = GNumBlock[7];
        }
    #endif
        if(GNumBlock[7] == 0x20 || GNumBlock[7] == 0x30){
            PosParam.PosMult16 = 16; 
        }else if(GNumBlock[7] == 0x10 || GNumBlock[7] == 0x60){
            PosParam.PosMult16 = 1;
        }
        
    #ifdef SEGLCD
        if(GNumBlock[7] == 0x10 || GNumBlock[7] == 0x30){
            disp.Symbols (ModeTime); // ??
        }else if(GNumBlock[7] == 0x20 || GNumBlock[7] == 0x60){
            disp.Symbols (ModePulse); // ??
        }
    #endif

        PosParam.StopSec = ((uint16_t)GNumBlock[8] << 8) + (uint16_t)GNumBlock[9];
        PosParam.Amtall = 0;  //??????

        disp.segDash(2);
        disp.OneNum(3, 0, PosParam.MeasureMode / 16);       // ????????
        disp.OneNum(4, 0, PosParam.MeasureMode % 16);
        disp.segDash(5);
    }

#ifdef DUAL_MODE
    if(GNumBlock[1] == CARD_03_VER){
        if(GNumBlock[7] != 0x10 && GNumBlock[7] != 0x20 && GNumBlock[7] != 0x30 && GNumBlock[7] != 0x60){
            disp.ErrorCode(805);        // ??????
            CheckCardOn();
            return;
        }
        PosParam.DualControlMode_2 = GNumBlock[7];
        PosParam.StopSec = ((uint16_t)GNumBlock[8] << 8) + (uint16_t)GNumBlock[9];
        disp.OneNum(2, 0, '_');
        disp.OneNum(3, 0, PosParam.DualControlMode_2 / 16);         // ????????
        disp.OneNum(4, 0, PosParam.DualControlMode_2 % 16);
        disp.OneNum(5, 0, '_');
    }
#endif

    PosParam.SaveParam();
    SaveAmountFun();
    Beep.BeepOnce();
}

static void OperCard_F2(void)
{
    PosParam.M1Purse.Sector = GNumBlock[2]; //存储扇区
    disp.OneNum(3, 0, GNumBlock[2] / 10);
    disp.OneNum(4, 0, GNumBlock[2] % 10);   
    PosParam.ChargeDelay = GNumBlock[4];     //延时扣费时间
    
    #ifdef SEGLCD
    if(GNumBlock[14] == 0x5A)    //液晶屏背光关闭标记
    { 
        disp.Backlight (off);
        PosParam.BackLight = 0;
    } else {
        PosParam.BackLight = 1;
    }
    #endif 
    
    PosParam.CPU_B = 0;

    setDefaultKey[0] = GNumBlock[7];
    setDefaultKey[1] = GNumBlock[8];
    setDefaultKey[2] = GNumBlock[9];
    setDefaultKey[3] = GNumBlock[11];
    setDefaultKey[4] = GNumBlock[12];
    setDefaultKey[5] = GNumBlock[13];

    memmove((void *)PosParam.M1Purse.Key, setDefaultKey, 6);     // 将默认密钥复制到 M1 钱包的密钥区域
  

    PosParam.SaveParam();
    //PosParam.SaveWorkParam();

    Beep.BeepOnce();
}
//F3
static void OperCard_F3(void)
{
    if(GNumBlock[11] == 0x5A) {
        PosParam.FreeUseMode = 1;    //免费用量开启标记位
        if(GNumBlock[4] == 0xFF) {
            PosParam.FreeUseTotal = GNumBlock[7];   //??????
            PosParam.FreeUseMonFlag = 0;
            disp.OneNum(3, 0, PosParam.FreeUseTotal /100%10);
            disp.OneNum(4, 0, PosParam.FreeUseTotal /10%10);
            disp.OneNum(5, 0, PosParam.FreeUseTotal %10);
        }
        if(GNumBlock[4] == 0x5A) {
            PosParam.FreeUseTotal   = ((uint16_t)GNumBlock[12] << 8) + (uint16_t)GNumBlock[13];
            PosParam.FreeUseMonFlag = 1;
            disp.OneNum(1, 0, PosParam.FreeUseTotal / 10000 % 10);
            disp.OneNum(2, 0, PosParam.FreeUseTotal / 1000 % 10);
            disp.OneNum(3, 0, PosParam.FreeUseTotal / 100 % 10);
            disp.OneNum(4, 0, PosParam.FreeUseTotal / 10 % 10);
            disp.OneNum(5, 0, PosParam.FreeUseTotal % 10);
        }
        PosParam.FreeUseFee = GNumBlock[8];     //???????????
        PosParam.FreeUsePluse = GNumBlock[9];     //????????

        if(GNumBlock[14] == 0xff) {    
            GNumBlock[14] = 1; 
        }
        PosParam.FreeRemWarn = 10*GNumBlock[14];   
        
        delay_ms(500);
        disp.OneNum(1, 0, PosParam.FreeUseFee / 16);
        disp.OneNum(2, 0, PosParam.FreeUseFee % 16);
        disp.segDash(3);    // ?? -
        disp.OneNum(4, 0, PosParam.FreeUsePluse / 16);
        disp.OneNum(5, 0, PosParam.FreeUsePluse % 16);
    }else{   
        PosParam.FreeUseMode = 0;
    }
    
    PosParam.SaveParam();
    Beep.BeepOnce(); 
}

//????
static void OperCard_F7(void)
{
    if(GNumBlock[7] == 0x5A){
        PosParam.RationModeTime = ((uint16_t)GNumBlock[8] << 8) + (uint16_t)GNumBlock[9]; // ????
        PosParam.RationModeFee = GNumBlock[11];
        PosParam.RationMode = 1;

        if(GNumBlock[14] == 0x5A){   
            PosParam.RationInCrad = 1; 
        }else{   
            PosParam.RationInCrad = 0; 
        }

        disp.WriteMulDig(1, 5, PosParam.RationModeTime);
    }else{   
        PosParam.RationMode = 0; 
    }

    PosParam.SaveParam();
    Beep.BeepOnce();
}
//??CPU?? B??
static void OperCard_F9(void)
{
    #ifdef SEGLCD
    if(GNumBlock[14] == 0x5A) {              //??X1E(01??0E??)????5A?????????????
        disp.Backlight (off);
        PosParam.BackLight = 0;
    }else{	
        PosParam.BackLight = 1; 
    }
    #endif

    if (GNumBlock[1] == 0x5A) {  
        PosParam.CPU_B = 1;  
    }else{
        PosParam.CPU_B = 0;
    }

    PosParam.M1Purse.Sector = GNumBlock[2]; //????
    disp.OneNum(3, 0, GNumBlock[2] / 10);
    disp.OneNum(4, 0, GNumBlock[2] % 10);   
    PosParam.ChargeDelay = GNumBlock[4];     //?????????
    setDefaultKey[0] = GNumBlock[7];
    setDefaultKey[1] = GNumBlock[8];
    setDefaultKey[2] = GNumBlock[9];
    setDefaultKey[3] = GNumBlock[11];
    setDefaultKey[4] = GNumBlock[12];
    setDefaultKey[5] = GNumBlock[13];
    memmove((void *)PosParam.M1Purse.Key, setDefaultKey, 6);

    PosParam.SaveParam();
    //PosParam.SaveBaseParam();
    Beep.BeepOnce();
}

#ifdef DUAL_MODE
static void OperCard_00(uint8_t aPlus)
{
    static uint32_t  Pulse;
    static uint32_t Time_count;

    switch (aPlus){
    case 0:
        Pulse = PosParam.Out1Pulse;
        if(Pulse == 0){    
            Pulse = 0xff;
        }else{
            Pulse --; 
        }
        break;
    case 1:
        Pulse = PosParam.Out1Pulse;
        Pulse ++; 
        if(Pulse > 0xff){    
            Pulse = 0;
        }   
        break;
    case 2:
        Pulse = PosParam.Out2Pulse;
        if(Pulse == 0){    
            Pulse = 0xff;
        }else{
            Pulse --;  
        }
        break;
    case 3:
        Pulse = PosParam.Out2Pulse;
        Pulse ++; 
        if(Pulse > 0xff){    
            Pulse = 0;
        }   
        break;
    default:
        break;
    }

    disp.OneNum(2, 0, Pulse / 100 % 10);
    disp.OneNum(3, 0, Pulse / 10 % 10);
    disp.OneNum(4, 0, Pulse % 10);

    disp.OneNum(1, 0, '-');
    disp.OneNum(5, 0, '-');

    Beep.BeepTwinkle();

    SetTime13_Counter (on);
    while (CheckM1Card() == nil) {
        if (Time13_Count >= 2400) {      // ????3????????????1
            if((Time13_Count-2450) >= 150 && Time13_Count != Time_count) {  // Time_Num-3000) >= 200  ??3??
                Time_count = Time13_Count;
                if (aPlus == 1 || aPlus == 3) {
                    Pulse ++; 
                    if(Pulse > 0xff){    
                        Pulse = 0;
                    }
                }else{     
                    if(Pulse == 0){    
                        Pulse = 0xff;
                    }else{
                        Pulse --;
                    }
                }       
                
                BEEP_ON;
                delay_ms(20);
                BEEP_OFF;

                disp.OneNum(2, 0, Pulse / 100 % 10);
                disp.OneNum(3, 0, Pulse / 10 % 10);
                disp.OneNum(4, 0, Pulse % 10);

                Time13_Count = 2450;
            } 
        }
    }
    
    if(Pulse == 0){
        disp.ErrorCode(601);
        Pulse = 1;
    }

    SetTime13_Counter(off);
    if (aPlus == 0 || aPlus == 1) {
        PosParam.Out1Pulse = Pulse;
    }else{
        PosParam.Out2Pulse = Pulse;
    }

    PosParam.SaveParam();
    delay_ms(500);
}
//????
static void OperCard_F6(void)
{
    if (GNumBlock[13] == 0x5A) {               // 3=5A(????????????,???????)
        PosParam.DualMode = 0;
        PosParam.PulseOutMode = 0x5A;
        disp.OneNum(2,0,'P');
        disp.OneNum(3,0,'O');
        disp.OneNum(4,0,'U');
        disp.OneNum(5,0,'T');
    } else if(GNumBlock[7] == 0x5A) { // 1=5A(????????????,???????)
        Init_Key();
        PosParam.DualMode = 0x5A;
        PosParam.Out1Pulse = (uint16_t)GNumBlock[8];  // ??1??(????) ????(????)???????????????
        PosParam.Out1Fee   = (uint16_t)GNumBlock[9];  // ??1??(????) ??????????(????)
        PosParam.Out2Pulse = (uint16_t)GNumBlock[11]; // ??2??(????) ????(????)???????????????
        PosParam.Out2Fee   = (uint16_t)GNumBlock[12]; // ??2??(????) ??????????(????)
        
        disp.OneNum(2,0,'O');
        disp.OneNum(3,0,'N');

        if (GNumBlock[1] == 0x5A) {
            if(PosParam.MeasureMode == 0x10) {
                PosParam.DualControlMode_1 = 0x10;
                PosParam.DualControlMode_2 = 0x20;
            } else if(PosParam.MeasureMode == 0x20) {
                PosParam.DualControlMode_1 = 0x20;
                PosParam.DualControlMode_2 = 0x10;
            } else if(PosParam.MeasureMode == 0x30) {
                PosParam.DualControlMode_1 = 0x30;
                PosParam.DualControlMode_2 = 0x60;
            } else if(PosParam.MeasureMode == 0x60) {
                PosParam.DualControlMode_1 = 0x60;
                PosParam.DualControlMode_2 = 0x30;
            }
            PosParam.DualControlMode = 0x5A;
        } else if (GNumBlock[1] == 0x6A) {
            if(PosParam.MeasureMode == 0x10 || PosParam.MeasureMode == 0x60) {
                PosParam.DualControlMode_1 = 0x60;
                PosParam.DualControlMode_2 = 0x60;
            } else if(PosParam.MeasureMode == 0x20 || PosParam.MeasureMode == 0x30) {
                PosParam.DualControlMode_1 = 0x20;
                PosParam.DualControlMode_2 = 0x20;
            }
            PosParam.DualControlMode = 0X6A;
        } else {
            PosParam.DualControlMode_1 = PosParam.MeasureMode;
            PosParam.DualControlMode_2 = PosParam.MeasureMode;
            PosParam.DualControlMode = 0x01;
        }
    } else {   
        PosParam.DualMode = 0;
        PosParam.PulseOutMode = 0;
        disp.OneNum(2,0,'O');
        disp.OneNum(3,0,'F');
        disp.OneNum(4,0,'F');
    }

    if(PosParam.Out1Pulse == 0 || PosParam.Out2Pulse == 0) {
        disp.ErrorCode(601);
        PosParam.Out1Pulse = 1;
        PosParam.Out2Pulse = 1;
    }
    
    PosParam.SaveParam();
    Beep.BeepOnce();
}
//????????
static void OperCard_FD(void)
{
    if(GNumBlock[1] == 0x5A) {
        Init_Key();
        PosParam.Dual_RationMode = 1;

        PosParam.Dual_1RationModeFee = ((uint16_t)GNumBlock[9] << 8) + (uint16_t)GNumBlock[11];
        PosParam.Dual_1RationModeTime = ((uint16_t)GNumBlock[7] << 8) + (uint16_t)GNumBlock[8];
        PosParam.Dual_2RationModeFee = ((uint16_t)GNumBlock[14] << 8) + (uint16_t)GNumBlock[4];
        PosParam.Dual_2RationModeTime = ((uint16_t)GNumBlock[12] << 8) + (uint16_t)GNumBlock[13];
        disp.OneNum(2,0,'O');
        disp.OneNum(3,0,'N');
    } else {   
        PosParam.Dual_RationMode = 0; 
        DualRatMode.Incr = 0;
        disp.OneNum(2,0,'O');
        disp.OneNum(3,0,'F');
        disp.OneNum(4,0,'F');
    }
    G_key1_flag = 0 ;
    G_key2_flag = 0 ;
    
    PosParam.SaveParam();
    Beep.BeepOnce();
}
//FD ???? ??????
static void OperCard_D8(void)
{
    if (!PosParam.Dual_RationMode){
        disp.OneNum(2,0,'F');
        disp.OneNum(3,0,'D');

        Beep.BeepGap(3);
        return;
    } 
    
    if(GNumBlock[1] == 0x5A){
        DualRatMode.Incr = 1;
        disp.OneNum(2,0,'O');
        disp.OneNum(3,0,'N');
    } else{
        DualRatMode.Incr = 0;
        disp.OneNum(2,0,'O');
        disp.OneNum(3,0,'F');
        disp.OneNum(4,0,'F');
    }

    PosParam.SaveParam();
    Beep.BeepOnce();
}
#endif
//??????
static void OperCard_8C(void)
{
    if(GNumBlock[7] == 0x5A){
        PosParam.NFC_Gain = PosParam.NFC_Gain + 0x10;
        if(PosParam.NFC_Gain == 0x88) {
            PosParam.NFC_Gain = 0x38;
        }
    }
    disp.OneNum(2, 0, PosParam.NFC_Gain / 16);
    disp.OneNum(3, 0, PosParam.NFC_Gain % 16);  

	WriteRawRC ( RFCfgReg, PosParam.NFC_Gain );     //??????

    PosParam.SaveParam();
    Beep.BeepOnce(); 
}
#ifndef SEGLCD
//??LED??????
static void OperCard_8D(void)
{
    if(GNumBlock[7] == 0x5A)
    {
        PosParam.LedLumin = PosParam.LedLumin + 1;
        if(PosParam.LedLumin > 0x8F) {
            PosParam.LedLumin = 0x88;
        }
        if(PosParam.LedLumin < 0x88) {
            PosParam.LedLumin = 0x8f;
        }
    }
    disp.OneNum(2, 0, PosParam.LedLumin / 16);
    disp.OneNum(3, 0, PosParam.LedLumin % 16);  

	TM1638_WriteCmd(0x88 | PosParam.LedLumin);       //???? (0x88-0x8f)8??????

    PosParam.SaveParam();
    Beep.BeepOnce(); 
}
#endif
// OperCardTask ???????????
void OperCardTask()
{
    disp.Clear();
#ifdef SEGLCD   
    disp.sHEX(6, GNumBlock[5]); //6??7 ??????
#elif defined DIGLED
    disp.OneNum (7,1, GNumBlock[5]/16 ); //7 ??????
    disp.OneNum (8,1, GNumBlock[5]%16 ); //8 ??????
#endif
    switch (GNumBlock[5]) {
        case 0x05://????
            PosIP_PlusMinus(1);
            break;
        case 0x06://????
            PosIP_PlusMinus(0);
            break;
        case 0x22:   // ????????/????
            if(JudgeAuthCode())  break;
            OperCard_22();
            break;
        case 0x24: // ?????????????
            if(JudgeAuthCode())  break;
            OperCard_24();
            break;
        case 0x25: //????
            if(JudgeAuthCode())  break;
            OperCard_25();
            break;
		case 0x81: // ????????
            OperCard_81();
            break;
        case 0x91: // ?????????????
            ConsumePlusMinus (1);
            break;
        case 0x90: // ?????????????
            ConsumePlusMinus (0);
            break;
        case 0x9A: // ?????
            if(JudgeAuthCode())  break;
            OperCard_9A();
            break;
        case 0x9C: // ??????
            CardSetClock();
            break;
        case 0xCC: // ????
            if(JudgeAuthCode())  break;
            DoSet_CC_Card(); 
            break;
        case 0xD5: // ?????????????
            OperCard_D5();
            break;
        case 0xD6: // ?????????
            OperCard_D6();
            break;
        case 0xF1: //S etMeatureMode  ????????00 ???? 20 ??????? 60 ???? ???????????
            OperCard_F1();
            break;
        case 0xF2: // ?????????????????????
            OperCard_F2();
            break;
        case 0xF3: // ????
            OperCard_F3();
            break;
        case 0xF7: // ??????
            OperCard_F7();
            break;
        case 0xF9: 
            OperCard_F9();
            break;
        case 0x8C: 
            OperCard_8C();
            break;
#ifndef SEGLCD     
        case 0x8D: 
            OperCard_8D();
            break;
#endif
     
#ifdef DUAL_MODE       
        case 0x00:    // ???????????????
            OperCard_00(0);
            break;
        case 0x01:    // ???????????????
            OperCard_00(1);
            break;
        case 0x02:    // ???????????????
            OperCard_00(2);
            break;
        case 0x03:    // ???????????????
            OperCard_00(3);
            break;
        case 0xFD: // ??????
            OperCard_FD();
            break;
        case 0xF6:
            OperCard_F6();
            break;
        case 0xD8:
            if(JudgeAuthCode())  break;
            OperCard_D8();
            break;
#endif
        default:
            disp.ErrorCode(404); // ??????
            CheckCardOn();
            break;
    }

#ifdef SEGLCD 
    disp.Symbols(okLine);
#endif

    CheckCardOn();
    disp.Clear();
}


